home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / festival / tobi_rules.scm < prev    next >
Encoding:
Text File  |  2006-12-20  |  34.6 KB  |  1,003 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;                                                                       ;;
  3. ;;;                Centre for Speech Technology Research                  ;;
  4. ;;;                     University of Edinburgh, UK                       ;;
  5. ;;;                       Copyright (c) 1996,1997                         ;;
  6. ;;;                        All Rights Reserved.                           ;;
  7. ;;;                                                                       ;;
  8. ;;;  Permission is hereby granted, free of charge, to use and distribute  ;;
  9. ;;;  this software and its documentation without restriction, including   ;;
  10. ;;;  without limitation the rights to use, copy, modify, merge, publish,  ;;
  11. ;;;  distribute, sublicense, and/or sell copies of this work, and to      ;;
  12. ;;;  permit persons to whom this work is furnished to do so, subject to   ;;
  13. ;;;  the following conditions:                                            ;;
  14. ;;;   1. The code must retain the above copyright notice, this list of    ;;
  15. ;;;      conditions and the following disclaimer.                         ;;
  16. ;;;   2. Any modifications must be clearly marked as such.                ;;
  17. ;;;   3. Original authors' names are not deleted.                         ;;
  18. ;;;   4. The authors' names are not used to endorse or promote products   ;;
  19. ;;;      derived from this software without specific prior written        ;;
  20. ;;;      permission.                                                      ;;
  21. ;;;                                                                       ;;
  22. ;;;  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        ;;
  23. ;;;  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      ;;
  24. ;;;  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   ;;
  25. ;;;  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     ;;
  26. ;;;  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    ;;
  27. ;;;  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   ;;
  28. ;;;  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          ;;
  29. ;;;  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       ;;
  30. ;;;  THIS SOFTWARE.                                                       ;;
  31. ;;;                                                                       ;;
  32. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  33. ;;;                Authors: Robert A. J. Clark and Alan W Black
  34. ;;;                Modifications and Checking: 
  35. ;;;                         Gregor Moehler (moehler@ims.uni-stuttgart.de)
  36. ;;;                         Matthew Stone (mdstone@cs.rutgers.edu)
  37. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  38. ;;;
  39. ;;; Generate F0 points from tobi labels using rules given in:
  40. ;;; Jilka, Moehler & Dogil (forthcomming in Speech Communications)
  41. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  42. ;;;
  43. ;;;  *** Converted to new Relation architecture -- but not checked yet -- awb
  44. ;;;      -> crude (beta) checking: gm in Dec. 98
  45. ;;;
  46. ;;;      -> fixed TAKEOVER bug that used time value 
  47. ;;;         as pitch target (!) - MDS 1/02
  48. ;;;      -> hacked around bunches of target overlap problems - MDS 1/02
  49. ;;;      -> added primitive pitch range controls
  50. ;;;      
  51. ;;;  Known problems and bugs:
  52. ;;;      Can't currently use voicing intervals which cross syllable boundaries,
  53. ;;;      so pre/post-nuclear tones are currently places 0.2s before/after the 
  54. ;;;      nuclear tone even if no voicing occurs. Failing this they default a
  55. ;;;      percentage of the voicing for that syllable. 
  56. ;;; 
  57. ;;;      Don't know about target points ahead of the current syllable.
  58. ;;;      (As you need to know what comes before them to calculate them)
  59. ;;;      So: post accent tones are placed 0.2 ahead if following syllable exists
  60. ;;;          ends before 0.2 from starred target and is not accented
  61. ;;;      The H-target of the H+!H* is 0.2 sec instead of 0.15 sec before 
  62. ;;;      starred tone.
  63. ;;;      
  64. ;;;      Multi-utterance input has not been tested. 
  65. ;;;      
  66. ;;;      !H- does not generate any targets
  67. ;;;      
  68. ;;;      Unfortunaltely some other modules may decide to put pauses in the 
  69. ;;;      middle of a phrase
  70. ;;;      
  71. ;;;      valleys are not tested yet
  72. ;;;      
  73. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  74. ;;;
  75. ;;;  To use this in a voice 
  76. ;;;     (require 'tobi_rules)
  77. ;;;  And in the voice call
  78. ;;;     (setup_tobi_f0_method)
  79. ;;;  Set the following for your speaker's F0 range
  80. ;;;  (Parameter.set 'Default_Topline 146)
  81. ;;;  (Parameter.set 'Default_Start_Baseline 61)
  82. ;;;  (Parameter.set 'Valley_Dip 75)
  83.  
  84. ;; level of debug printout
  85. (set! printdebug 0)
  86.  
  87. (define (setup_tobi_f0_method)
  88.   "(setup_tobi_f0_method)
  89. Set up parameters for current voice to use the implementaion
  90. of ToBI labels to F0 targets by rule."
  91.   (Parameter.set 'Int_Method Intonation_Tree)
  92.   (Parameter.set 'Int_Target_Method Int_Targets_General)
  93.   (set! int_accent_cart_tree no_int_cart_tree) ; NONE always
  94.   (set! int_tone_cart_tree   no_int_cart_tree) ; NONE always
  95.   (set! int_general_params
  96.     (list 
  97.      (list 'targ_func tobi_f0_targets)))   ; we will return a list of f0 targets here
  98.  
  99.   (Parameter.set 'Phrase_Method 'cart_tree)
  100.   (set! phrase_cart_tree tobi_label_phrase_cart_tree) ; redefines the phrasebreak tree
  101.   t)
  102.  
  103. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  104. ;;;;;;
  105. ;;;;;; Define and set the new f0 rules
  106. ;;;;;;
  107. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  108.  
  109. ;;; Set global parameters
  110. ;;; You may want to reset these for different speakers
  111.  
  112. (Parameter.set 'Default_Topline 146) ;146
  113. (Parameter.set 'Default_Start_Baseline 61) ;61
  114. (Parameter.set 'Current_Topline        (Parameter.get 'Default_Topline))
  115. (Parameter.set 'Current_Start_Baseline (Parameter.get 'Default_Start_Baseline))
  116. (Parameter.set 'Current_End_Baseline   (Parameter.get 'Current_Start_Baseline))
  117. (Parameter.set 'Downstep_Factor 0.70)
  118. (Parameter.set 'Valley_Dip 75)
  119. ;;; function to add target points on a given syllable and fill in 
  120. ;;; targets where necessary
  121.  
  122. (define (tobi_f0_targets utt syl)
  123.   "(tobi_f0_targets UTT ITEM)
  124.    Returns a list of targets for the given syllable."
  125.   (if (and (>= printdebug  1)
  126.        (not(equal? 0 (item.feat syl "R:Intonation.daughter1.name"))))
  127.       (format t "### %l (%.2f %.2f) %l ptarg: %l ###\n" (item.name syl)
  128.           (item.feat syl "syllable_start")(item.feat syl "syllable_end")
  129.           (item.feat syl "R:Intonation.daughter1.name") (ttt_last_target_time syl)))
  130.   
  131.   ;; only continue if there is a Word related to this syllable
  132.   ;; I know there always should be, but there might be a bug elsewhere
  133.   (cond 
  134.    ((not(equal? 0 (item.feat syl "R:SylStructure.parent.name")))
  135.  
  136.     ; get current label. This assumes that there is only one accent and
  137.     ; one endtone on a syllable. Although there can be one of each.
  138.     (let ((voicing  (ttt_get_voice_times syl))                ; voicing interval
  139.       (pvoicing (ttt_get_voice_times                      ; previous voicing
  140.              (item.relation.prev syl 'Syllable)))
  141.       (nvoicing (ttt_get_voice_times                      ; next voicing
  142.              (item.relation.next syl 'Syllable))))
  143.  
  144.     ; if first syl of phrase set Phrase_Start and Phrase_End parameters
  145.     ; and reset downstep (currently does so on big and little breaks.)
  146.     ; only assignes Default values at this stage 
  147.     ; maybe trained from CART later - first steps now - MDS
  148.     ; following Moehler and Mayer, SSW 2001 
  149.     (if   (eq 0 (item.feat syl 'syl_in)) ;; GM maybe something better needed here?
  150.     (progn
  151.      (Parameter.set 'Phrase_Start (item.feat syl 'R:SylStructure.parent.R:Phrase.last.word_start))
  152.      (Parameter.set 'Phrase_End (item.feat syl 'R:SylStructure.parent.R:Phrase.last.word_end))
  153.      (Parameter.set 'Current_Topline 
  154.             (/ (* (wagon syl ttt_topline_tree) 
  155.                   (Parameter.get 'Default_Topline)) 100))
  156.      (Parameter.set 'Current_Start_Baseline
  157.             (/ (* (wagon syl ttt_baseline_tree)
  158.                   (Parameter.get 'Default_Start_Baseline)) 100))
  159.      (Parameter.set 'Current_End_Baseline 
  160.             (Parameter.get 'Current_Start_Baseline))
  161.      (if (>= printdebug  3)
  162.          (begin 
  163.            (print (format nil "new range: %f %f %f" 
  164.                   (Parameter.get 'Current_Topline) 
  165.                   (Parameter.get 'Current_Start_Baseline)
  166.                   (Parameter.get 'Current_End_Baseline) ))))  ))
  167.  
  168.     ; do stuff (should go only if there is an accent/boundary?)
  169.     (let ((new_targets 
  170.        (ttt_to_targets syl (wagon syl ttt_starttone_tree)
  171.                voicing
  172.                pvoicing
  173.                nvoicing
  174.                'Starttones)))
  175.  
  176.     (set! new_targets (append new_targets 
  177.        (ttt_to_targets syl (wagon syl ttt_accent_tree)
  178.                voicing 
  179.                pvoicing 
  180.                nvoicing 
  181.                'Accents)))
  182.  
  183.     (set! new_targets (append new_targets 
  184.        (ttt_to_targets syl (wagon syl ttt_endtone_tree)
  185.                voicing
  186.                pvoicing
  187.                nvoicing
  188.                'Endtones)))
  189.  
  190.     (if (and(not(equal? new_targets nil))
  191.         (>= printdebug  2))
  192.     (begin
  193.       (format t ">> Targets: %l\n" new_targets)
  194.       (format t ">> LastTarget: %l\n" (last new_targets))
  195.       ))
  196.  
  197.       new_targets)))))
  198.  
  199.  
  200. ;;; CART tree to specify no accents
  201.  
  202. (set! no_int_cart_tree
  203. '
  204. ((NONE)))
  205.  
  206. ;;;
  207. ;;; Relate phrasing to boundary tones.
  208. ;;;   Added downstepped tones - MDS
  209.  
  210. (set! tobi_label_phrase_cart_tree
  211. '
  212. ((tone in ("L-" "H-" "!H-"))
  213.  ((B))
  214.  ((tone in ("H-H%" "H-L%" "!H-L%" "L-L%" "L-H%"))
  215.   ((BB))
  216.   ((NB)))))
  217.  
  218. ;;;
  219. ;;;  The other functions
  220. ;;;
  221.  
  222. ;;; process a list of relative targets and convert to actual targets
  223.  
  224. (define (ttt_to_targets syl rlist voicing pvoicing nvoicing type)
  225.   "Takes a list of target sets and returns a list of targets."
  226.   (if (or (and (>= printdebug  2)
  227.            rlist (atom (caar rlist)) 
  228.            (not (equal? 'NONE (caar rlist))) (not (equal? '(NONE) (caar rlist))))
  229.       (>= printdebug  3)) 
  230.        (begin (print "Entering ttt_to_targets with:")
  231.     (print (format nil "rlist: %l vc: %l pvc: %l nvc: %l type: %s" rlist voicing pvoicing nvoicing type))))
  232. (cond 
  233.  ;; nowt
  234.  ((eq (length rlist) 0) ())
  235.  ;; a single target set
  236.  ((atom (car (car rlist)))
  237.   (cond
  238.    ((eq type 'Accents)
  239.     (ttt_accent_set_to_targets syl rlist voicing pvoicing nvoicing))
  240.    ((eq type 'Starttones)
  241.     (ttt_bound_set_to_targets syl rlist voicing pvoicing))
  242.    ((eq type 'Endtones)
  243.     (ttt_bound_set_to_targets syl rlist voicing pvoicing))
  244.    (t (error "unknown target set encountered in ttt_to_targets"))))
  245.  ;; list of target sets
  246.  ((atom (car (car (car rlist))))
  247.   (append (ttt_to_targets syl (cdr rlist) voicing pvoicing nvoicing type)
  248.       (ttt_to_targets syl (car rlist) voicing pvoicing nvoicing type)))
  249.  ;; error
  250.  (t (error "something strange has happened in ttt_to_targets"))))
  251.  
  252.  
  253. ;; process a starttone/endtone target set.
  254.  
  255. (define (ttt_bound_set_to_targets syl tset voicing pvoicing)
  256.   "takes a start/endtone target set and returns a list of target points."
  257.   (if (>= printdebug  3) (begin
  258.       (print "Entering ttt_bound_set_to_targets with:")
  259.       (pprintf (format nil "tset: %l vc: %l pvc: %l" tset voicing pvoicing))))
  260.   (cond
  261.    ;; usually target given is NONE. (also ignore unknown!)
  262.    ((or (eq (car (car tset)) 'NONE)
  263.     (eq (car (car tset)) 'UNKNOWN))
  264.     nil)
  265.    ;; a pair of target pairs
  266.    ((eq (length tset) 2)
  267.     (list (ttt_get_target (car tset) voicing) 
  268.       (ttt_get_target (car (cdr tset)) voicing)))
  269.    ;; single target pair
  270.    ((eq (length tset) 1)
  271.     (cond
  272.      ;; an actual target pair
  273.      ((not (null (cdr (car tset))))
  274.       (list (ttt_get_target (car tset) voicing)))
  275.      ;; a TAKEOVER marker
  276.      ((eq (car (car tset)) 'TAKEOVER)
  277.       (list (list (ttt_interval_percent voicing 0) 
  278.           (ttt_last_target_value syl))))
  279.      (t (error "unknown target pair in ttt_bound_set_to_targets"))))
  280.    (t (error "unknown target set type in ttt_bound_set_to_targets"))))
  281.  
  282.  
  283. ;; process an accent target set.
  284.  
  285. (define (ttt_accent_set_to_targets syl tset voicing pvoicing nvoicing)
  286.   "takes a accent target set and returns a list of target points."
  287.   (if (>= printdebug  3) (begin
  288.       (print "Entering ttt_accent_set_to_targets with:")
  289.       (pprintf (format nil "tset: %l vc: %l pvc: %l nvc: %l" tset voicing pvoicing nvoicing))))
  290.   (cond
  291.    ;; single target in set
  292.    ((null (cdr tset)) 
  293.     (cond
  294.      ; target given is NONE.
  295.      ((or (eq (car (car tset)) 'NONE)
  296.       (eq (car (car tset)) 'UNKNOWN)) nil) 
  297.      ; V1 marker
  298.      ((eq (car (car tset)) 'V1)
  299.       (let ((target_time (+ (/ (- (next_accent_start syl)
  300.                   (ttt_last_target_time syl))
  301.                    2.0)
  302.                 (ttt_last_target_time syl))))
  303.     (list (list target_time (ttt_accent_pitch (Parameter.get 'Valley_Dip) target_time)))))
  304.      ; V2 marker
  305.      ((eq (car (car tset)) 'V2)
  306.       (let ((target_time (+ (ttt_last_target_time syl) 0.25)))
  307.     (list (list target_time (ttt_accent_pitch (Parameter.get 'Valley_Dip) target_time)))))
  308.      ; V3 marker
  309.      ((eq (car (car tset)) 'V3)
  310.       (let ((target_time (- (next_accent_start syl) 0.25)))
  311.     (list (list target_time (ttt_accent_pitch (Parameter.get 'Valley_Dip) target_time)))))     
  312.      ; single target pair
  313.      (t (list (ttt_get_target (car tset) voicing)))))
  314.    ;; a pair of targets
  315.    ((length tset 2)
  316.     (cond
  317.      ;; a *ed tone with PRE type tone (as in L+H*)
  318.      ((eq (car (car tset)) 'PRE)
  319.       (let ((star_target (ttt_get_target (car (cdr tset)) voicing))
  320.         (last_target (parse-number(ttt_last_target_time syl))))
  321.     (cond
  322.      ; normal 0.2s case (currently doesn't check for voicing)
  323.      ((and (eqv? 0 (ip_initial syl))
  324.            (> (- (car star_target) 0.2) last_target))
  325.       (list  (list (- (car star_target) 0.2)
  326.                   (ttt_accent_pitch (car (cdr (car tset)))
  327.                      (- (car star_target) 0.2))) ; the time
  328.             star_target))
  329.  
  330.      ; 90% prev voiced if not before last target - Added back in MDS,
  331.      ; with parse-number added and new check for ip_initial
  332.      ((and (eqv? 0 (ip_initial syl))
  333.            (> (parse-number (ttt_interval_percent pvoicing 90))
  334.           (parse-number (ttt_last_target_time syl))))
  335.       (list (list (ttt_interval_percent pvoicing 90)
  336.               (ttt_accent_pitch (car (cdr (car tset)))
  337.                     (ttt_interval_percent pvoicing 90)))
  338.         star_target))
  339.  
  340.      ;  otherwise (UNTESTED) [NOTE: Voicing for this syllable only]
  341.      (t 
  342.       (list (list (ttt_interval_percent voicing 20)
  343.              (ttt_accent_pitch (car (cdr (car tset)))
  344.                        (ttt_interval_percent voicing 20)))
  345.            star_target)))))
  346.      ; a *ed tone with POST type tone (as L*+H)
  347.      ((eq (car(car(cdr tset))) 'POST)
  348.       (let ((star_target (ttt_get_target (car tset) voicing))
  349.         (next_target nil ) ; interesting problem
  350.         (next_syl (item.next syl)))
  351.  
  352.     (cond
  353.      ; normal 0.2s case (UNTESTED)
  354.      ((and (not (equal? next_syl nil))
  355.            (eq 0 (item.feat next_syl "accented")))
  356.       (cond
  357.        ((< (+ (car star_target) 0.2) (item.feat next_syl "syllable_end"))
  358.         (list star_target 
  359.           (list (+ (car star_target) 0.2) 
  360.             (ttt_accent_pitch (car (cdr (car (cdr tset))))
  361.                       (+ (car star_target) 0.2) ))))
  362.        (t 
  363.         
  364.         (list star_target
  365.             (list (ttt_interval_percent nvoicing 90)
  366.               (ttt_accent_pitch (car (cdr (car (cdr tset))))
  367.                         (ttt_interval_percent nvoicing 90) ))))))
  368.  
  369.      ; 20% next voiced (BUG: Can't do this as the next target hasn't been
  370.      ;                                                     calculated yet!)
  371.      (nil nil)
  372.      ;otherwise (UNTESTED)
  373.      (t (list star_target
  374.           (list (ttt_interval_percent voicing 90)
  375.             (ttt_accent_pitch (car (cdr (car (cdr tset))))
  376.                       (ttt_interval_percent voicing 90) )))))))
  377.      
  378.      (t 
  379.       ;; This case didn't use to happen, but now must 
  380.       ;; to avoid +H's clobbering endtones - MDS's hack.
  381.       (list (ttt_get_target (car tset) voicing)
  382.         (ttt_get_target (cadr tset) voicing)))))
  383.  
  384.    
  385.    ;; something else...
  386.    (t (error (format nil "unknown accent set in ttt_accent_set_to_targets: %l" tset)))))
  387.  
  388.  
  389.  
  390. (define (ttt_get_target pair voicing)
  391.   "Returns actual target pair, usually for a stared tone."
  392.   (if (>= printdebug  4) (begin
  393.       (print "Entering ttt_get_target with:")
  394.       (pprintf pair) (pprintf voicing)))
  395.   (list (ttt_interval_percent voicing (car pair))
  396.     (ttt_accent_pitch (car (cdr pair))
  397.               (ttt_interval_percent voicing (car pair)))))
  398.  
  399. (define (ttt_accent_pitch value time)
  400.   "Converts a accent pitch entry to a pitch value."
  401.   (if (>= printdebug  4) (begin
  402.       (print "Entering ttt_accent_pitch with:")
  403.       (pprintf value)))
  404.   (cond
  405.    ;; a real value
  406.    ((number? value) 
  407.     (ttt_interval_percent (list (ttt_get_current_baseline time)
  408.                 (Parameter.get 'Current_Topline))
  409.               value))
  410.    ;; Downstep then Topline
  411.    ((eq value 'DHIGH)
  412.     (progn
  413.      (Parameter.set 'Current_Topline (+ (ttt_get_current_baseline time)
  414.                     (* (Parameter.get 'Downstep_Factor)
  415.                        (- (Parameter.get 'Current_Topline)
  416.                           (ttt_get_current_baseline time)))))
  417.      (ttt_interval_percent (list (ttt_get_current_baseline time)
  418.                  (Parameter.get 'Current_Topline))
  419.                100)))
  420.      
  421.    ;; Unknown
  422.    (t  (error "Unknown accent pitch value encountered"))))
  423.  
  424.  
  425. (define (ttt_get_current_baseline v)
  426.   "Returns the current declined baseline at time v."
  427.   (if (>= printdebug  4) (begin
  428.       (print "Entering  ttt_get_current_baseline with:")
  429.       (pprintf v)))
  430.   (let ((h (Parameter.get 'Current_Start_Baseline))
  431.     (l (Parameter.get 'Current_End_Baseline))
  432.     (e (Parameter.get 'Phrase_End))
  433.     (s (Parameter.get 'Phrase_Start)))
  434.     (- h (* (/ (- h l) (- e s)) (- v s)))))
  435.  
  436. ;;; find the time n% through an inteval
  437.  
  438. (define (ttt_interval_percent pair percent)
  439.   "Returns the time that is percent percent thought the pair."
  440.   (if (>= printdebug  4) (begin
  441.       (print "Entering ttt_interval_percent with:")
  442.       (pprintf (format nil "%l, %l" pair percent))))
  443.   (cond
  444.    ; no pair given: just return nil
  445.    ((null pair) nil)
  446.    ; otherwise do the calculation
  447.    (t (let ((start (car pair))
  448.         (end (car(cdr pair))))
  449.     (+ start (* (- end start) (/ percent 100)))))))
  450.  
  451.  
  452. ;;;  Getting start and end voicing times in a syllable
  453.  
  454. (define (ttt_get_voice_times syl_item)
  455.   "Returns a pair of start time of first voiced phone in syllable and
  456. end of last voiced phone in syllable, or nil if syllable is nil"
  457.   (cond
  458.    ((null syl_item) nil)
  459.    (t (let ((segs (item.relation.daughters syl_item "SylStructure")))
  460.     (list
  461.      (item.feat (ttt_first_voiced segs) "segment_start")
  462.      (item.feat (ttt_first_voiced (reverse segs)) "end"))))))
  463.  
  464. (define (ttt_first_voiced segs)
  465.   "Returns first segment that is voiced (vowel or voiced consonant)
  466. returns last segment if all are unvoiced."
  467.   (cond
  468.    ((null (cdr segs))
  469.     (car segs))  ;; last possibility
  470.    ((equal? "+" (item.feat (car segs) "ph_vc"))
  471.     (car segs))
  472.    ((equal? "+" (item.feat (car segs) "ph_cvox"))
  473.     (car segs))
  474.    (t
  475.     (ttt_first_voiced (cdr segs)))))
  476.  
  477. ;;; ttt_last_target has bifurcated into
  478. ;;;   ttt_last_target_time and
  479. ;;;   ttt_last_target_value 
  480. ;;; to fix a place where f0 was set to last target time!
  481. ;;;   - MDS
  482.  
  483. (define (ttt_last_target_time syl)
  484.   "Returns the end of the most recent previous target 
  485. in the utterance or nil if there is not one present
  486. "
  487.   (if (>= printdebug  3)
  488.       (begin (print "Entering  ttt_last_target_time")
  489.          (print syl))
  490.       )
  491.   (let ((target (ttt_last_target syl)))
  492.     (if (null? target)
  493.     nil
  494.     (item.feat target "R:Target.daughter1.pos"))))
  495.  
  496. (define (ttt_last_target_value syl)
  497.   "Returns the pitch of the most recent previous target 
  498. in the utterance or nil if there is not one present
  499. "
  500.   (if (>= printdebug  3)
  501.       (begin (print "Entering  ttt_last_target_time")
  502.          (print syl))
  503.       )
  504.   (let ((target (ttt_last_target syl)))
  505.     (if (null? target)
  506.     nil
  507.     (item.feat target "R:Target.daughter1.f0"))))
  508.  
  509. ;; Changed to scan through segments in the segment relation,
  510. ;; to catch (notional) targets on pauses.  - MDS
  511. ;;
  512. ;;; associated segments are:
  513. ;;; - the segments in the word
  514. ;;; - subsequent segments not in the syllable structure
  515. ;;; and on the first word, preceding segments
  516. ;;; not in the syllable structure 
  517.  
  518. (define (ttt_collect_following seg accum)
  519.   (if (or (null? seg)
  520.       (not (null? (item.relation seg 'SylStructure))))
  521.       accum
  522.       (ttt_collect_following (item.next seg) 
  523.                  (cons seg accum))))
  524.  
  525.  
  526. (define (ttt_last_target syl)
  527.   "Returns the most recent previous target 
  528. in the utterance or nil if there is not one present
  529. "
  530. (if (>= printdebug  3)
  531.     (begin (print "Entering  ttt_last_target")
  532.     (print syl))
  533.     )
  534.   (let ((prev_syl (item.relation.prev syl 'Syllable)))
  535.     (cond
  536. ;     ((symbol-bound? 'new_targets) (last (caar new_targets)))
  537.      ((null prev_syl) nil)
  538.      ((ttt_last_target_segs 
  539.        (ttt_collect_following 
  540.     (item.relation.next 
  541.      (item.relation.daughtern prev_syl "SylStructure")
  542.      "Segment")
  543.     (reverse (item.relation.daughters prev_syl "SylStructure")))))
  544.                     ;list of segments of prev. syllable
  545.                     ;in reverse order, with pauses
  546.                     ;prepended.
  547.      (t (ttt_last_target prev_syl)))))
  548.  
  549. (define (ttt_last_target_segs segs)
  550.   "Returns the first target no earlier than seg
  551. or nil if there is not one
  552. "
  553. (if (>= printdebug  4)
  554.     (begin (print "Entering  ttt_last_target_segs with:")
  555.        (pprintf (format nil "%l" segs))
  556. ))
  557.   (cond
  558.    ((null segs) nil)
  559.    ((and  (> (parse-number 
  560.           (item.feat  (car segs) "R:Target.daughter1.f0")) 0)
  561.       (eq 0 (item.feat (car segs) "R:SylStructure.parent.lisp_lh_condition"))
  562.       (eq 0 (item.feat (car segs) "R:SylStructure.parent.lisp_hl_condition"))
  563.       (eq 0 (item.feat (car segs) "R:SylStructure.parent.lisp_valley_condition")))
  564.     (car segs))
  565.    
  566.    (t (ttt_last_target_segs (cdr segs)))))
  567.  
  568. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  569. ;;;;;;
  570. ;;;;;; CART TREES                           (ttt - tobi to target)
  571. ;;;;;;
  572. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  573.  
  574. ;;;
  575. ;;; Return a list of target lists. A target list comprises of a list
  576. ;;; of related targets (ie for the L and H in L+H*), just to confuse
  577. ;;; matters each target is also a list! (pos pitch)
  578. ;;;
  579.  
  580.  
  581. (set! ttt_endtone_tree  ; BUG: does it check the current syl for last accent?
  582.       '
  583.       ((tobi_endtone is NONE)        ; ususally none
  584.        ((((NONE))))
  585.        ((tobi_endtone is "H-H%")     ; H-H%
  586.     ((((100 120))))
  587.     ((tobi_endtone is "L-L%")    ; L-L%
  588.      ((((100 -20))))
  589.      ((tobi_endtone is "L-H%")   ; L-H%
  590.       ((lisp_last_accent > 2)
  591.        ((lisp_last_accent_type is "L*") 
  592.         ((((0 25) (100 40))))    ; paper says 80 but AWB had 40
  593.         ((((0 0) (100 40)))))
  594.        ((lisp_last_accent_type is "L*")
  595.         ((((100 40))))
  596.         ((((50 0) (100 40))))))
  597.       ((tobi_endtone is "H-L%")  ; H-L%
  598.        ((lisp_last_accent_type is "L*")
  599.         ((tobi_accent is"L*")
  600.          ((((50 100) (100 100))))
  601.          ((((0 100) (100 100)))))
  602.         ((((100 100)))))
  603.       ((tobi_endtone is "!H-L%")  ; !H-L%
  604.        ((lisp_last_accent_type is "L*")
  605.         ((tobi_accent is"L*")
  606.          ((((50 DHIGH) (100 100))))
  607.          ((((0 DHIGH) (100 100)))))
  608.         ((((100 DHIGH)))))
  609.        ((tobi_endtone is "H-")
  610.         ((((100 100))))
  611.         ((tobi_endtone is "!H-")
  612.          ((((100 DHIGH))))
  613.          ((tobi_endtone is "L-")
  614.           ((((100 0))))
  615.           ((((UNKNOWN))))))))))))))
  616.  
  617. (set! ttt_starttone_tree
  618.       '
  619.       ((lisp_ip_initial = 1)
  620.        ((tobi_endtone is "%H")
  621.     ((((0 100))))
  622.     ((p.tobi_endtone in ("H-" "!H-" "L-"))
  623.      ((((TAKEOVER))))       ; takeover case
  624.      ((tobi_accent is NONE)  
  625.       ((lisp_next_accent > 2) ; default cases  (dep. on whether next target is low)
  626.        ((lisp_next_accent_type in ("L*" "L*+H" "L*+!H" "L+H*" "L+!H*" "L-" "L-H%" "L-L%"))
  627.         ((((0 50)(100 25))))
  628.         ((((0 50)(100 75)))))
  629.        ((lisp_next_accent_type in ("L*" "L*+H" "L*+!H" "L+H*" "L+!H*" "L-" "L-H%" "L-L%"))
  630.         ((((0 30))))
  631.         ((((0 70))))))
  632.       ((tobi_accent in ("L*" "L*+H" "L*+!H" "L+H*" "L+!H*" "L-" "L-H%" "L-L%"))
  633.         ((((0 30))))
  634.         ((((0 70))))))))
  635.        ((((NONE))))))     ; otherwise (and usually) nothing.  
  636.  
  637. ;; Redone after Jilka, Moehler and Dogil
  638. ;; - But treating one-syllable-ip's like
  639. ;; last-syllable-of-ip's in cases of 
  640. ;; two tone switches per syllable (e.g. H* L-H%). 
  641. ;; - And (hack) a 70% target for the initial 
  642. ;; H*'s of phrases when the next accent is L+H*
  643. ;; - MDS
  644.  
  645. (set! ttt_accent_tree
  646.       '
  647.       ((tobi_accent is "H*" )    ; H*
  648.        ((lisp_ip_final = 1)
  649.     ((lisp_ip_one_syllable_case = 1)
  650.      ((((50 100))))
  651.      ((((25 100)))))
  652.     ((lisp_hstar_weak_target = 1)
  653.      ((((60 70))))
  654.      ((lisp_ip_initial = 1) 
  655.       ((((85 100))))
  656.       ((((60 100)))))))
  657.  
  658.       ((tobi_accent is "!H*" )    ; !H*
  659.        ((lisp_ip_final = 1)
  660.     ((lisp_ip_one_syllable_case = 1)
  661.      ((((50 DHIGH))))
  662.      ((((25 DHIGH)))))
  663.        ((lisp_ip_initial = 1) 
  664.     ((((85 DHIGH))))
  665.     ((((60 DHIGH))))))
  666.  
  667.     ((tobi_accent is "L*" )    ; L*
  668.      ((lisp_ip_final = 1)
  669.       ((lisp_ip_one_syllable_case = 1)
  670.        ((((50 0))))
  671.        ((((25 0)))))
  672.       ((lisp_ip_initial = 1) 
  673.        ((((85 0))))
  674.        ((((60 0))))))
  675.  
  676.     ((tobi_accent is "L+H*")   ; L+H*
  677.      ((lisp_ip_final = 1)
  678.       ((lisp_ip_one_syllable_case = 1)
  679.        ((((PRE 20) (50 100))))  ; JMD estimated 70
  680.        ((((PRE 20) (25 100)))))
  681.       ((lisp_ip_initial = 1) 
  682.        ((((PRE 20) (90 100))))
  683.        ((((PRE 20) (75 100))))))
  684.  
  685.      ((tobi_accent is "L+!H*")   ; L+!H*
  686.      ((lisp_ip_final = 1)
  687.       ((lisp_ip_one_syllable_case = 1)
  688.        ((((PRE 20) (70 DHIGH))))
  689.        ((((PRE 20) (25 DHIGH)))))
  690.       ((lisp_ip_initial = 1) 
  691.        ((((PRE 20) (90 DHIGH))))
  692.        ((((PRE 20) (75 DHIGH))))))
  693.  
  694.       ((tobi_accent is "L*+H")   ; L*+H
  695.        ((lisp_ip_final = 1)
  696.         ((lisp_ip_one_syllable_case = 1)
  697.          ((((35 0) (80 100))))     ; POST would clobber endtones
  698.          ((((15 0) (40 100)))))    ; POST would clobber endtones - MDS
  699.         ((lisp_ip_initial = 1) 
  700.          ((((55 0) (POST 100))))
  701.          ((((40 0) (POST 100))))))
  702.  
  703.       ((tobi_accent is "L*+!H")   ; L*+!H
  704.        ((lisp_ip_final = 1)
  705.         ((lisp_ip_one_syllable_case = 1)
  706.          ((((35 0) (80 DHIGH))))    ; POST would clobber endtones - MDS
  707.          ((((15 0) (40 DHIGH)))))   ; POST would clobber endtones - MDS
  708.         ((lisp_ip_initial = 1) 
  709.          ((((55 0) (POST DHIGH))))
  710.          ((((40 0) (POST DHIGH))))))
  711.  
  712.        ((tobi_accent is "H+!H*")    ; H+!H* 
  713.         ((lisp_ip_final = 1)
  714.          ((lisp_ip_one_syllable_case = 1)
  715.           ((((PRE 143) (60 DHIGH)))) ; the 143 is a hack to level out the downstep
  716.           ((((PRE 143) (20 DHIGH)))))
  717.          ((lisp_ip_initial = 1) 
  718.           ((((PRE 143) (90 DHIGH))))
  719.           ((((PRE 143) (60 DHIGH))))))
  720.  
  721.         ((lisp_lh_condition = 1) 
  722.          ((((100 75))))
  723.          ((lisp_lh_condition = 2)
  724.           ((((0 90))))    
  725.           ((lisp_hl_condition = 1)
  726.            ((((100 25))))
  727.            ((lisp_valley_condition = 1)
  728.         ((((V1 85))))
  729.         ((lisp_valley_condition = 2)
  730.          ((((V2 70))))
  731.          ((lisp_valley_condition = 3)
  732.           ((((V3 70))))
  733.           ((tobi_accent is NONE)   ; usually we find no accent
  734.            ((((NONE))))
  735.            ((((UNKNOWN))))))))))))))))))))     ; UNKNOWN TARGET FOUND
  736.  
  737. ;;; Cart tree to "predict" pitch range
  738. ;;; Right now just accesses a feature
  739. ;;; "register" following Moehler & Mayer 2001.
  740. ;;; Register must be one of
  741. ;;;   H    - primary high register (default): 133% lowest, 92% highest
  742. ;;;   H-H  - expanded high register: 134% lowest, 100% highest
  743. ;;;   H-L  - lowered high register: 128% lowest, 87% highest
  744. ;;;   L    - primary low register: 100% lowest, 73% highest
  745. ;;;   L-L  and HL-L - low compressed: 100% lowest, 66% highest
  746. ;;;   HL   - expanded register:   100% lowest, 84% highest
  747. ;;;   HL-H - complete register:   100% lowest, 96% highest
  748. ;;; For their speaker, ,BASELINE was 42% of PEAK
  749.  
  750. (set! ttt_topline_tree 
  751.       '
  752.       ((R:SylStructure.parent.register is "H")
  753.        (92)
  754.        ((R:SylStructure.parent.register is "H-H")
  755.     (100)
  756.     ((R:SylStructure.parent.register is "H-L")
  757.      (87)
  758.      ((R:SylStructure.parent.register is "L")
  759.       (73)
  760.       ((R:SylStructure.parent.register is "L-L")
  761.        (66)
  762.        ((R:SylStructure.parent.register is "HL")
  763.         (84)
  764.         ((R:SylStructure.parent.register is "HL-H")
  765.          (96)
  766.          (92)))))))))
  767.  
  768. (set! ttt_baseline_tree 
  769.       '
  770.       ((R:SylStructure.parent.register is "H")
  771.        (133)
  772.        ((R:SylStructure.parent.register is "H-H")
  773.     (134)
  774.     ((R:SylStructure.parent.register is "H-L")
  775.      (128)
  776.      ((R:SylStructure.parent.register is "L")
  777.       (100)
  778.       ((R:SylStructure.parent.register is "L-L")
  779.        (100)
  780.        ((R:SylStructure.parent.register is "HL")
  781.         (100)
  782.         ((R:SylStructure.parent.register is "HL-H")
  783.          (100)
  784.          (133)))))))))
  785.  
  786. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  787. ;;;;;;
  788. ;;;;;;   Lisp Feature functions.
  789. ;;;;;;
  790. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  791.  
  792. (define (valley_condition syl)
  793. "(valley_condition syl)
  794. Function to determine if a lowered target between two high target points
  795. is needed in this syllable.
  796. Returns:  0 - no target required
  797.           1 - the single target case
  798.           2 - the first of the two target case
  799.           3 - the second of the two target case
  800. "
  801. (if (>= printdebug  4)
  802.     (begin (print "Entering valley_condition")))
  803. (cond
  804.  ((and (eq 0 (item.feat syl 'accented))
  805.        (string-matches (next_accent_type syl)
  806.                "\\(H\\*\\|H\\-\\|H\\-L\\%\\|H\\-H\\%\\|\\!H\\*\\|\\!H\\-\\|\\!H\\-L\\%\\|\\!H\\-H\\%\\)")
  807.        (string-matches (last_accent_type syl)
  808.                "\\(H\\*\\|L\\+H\\*\\|L\\*\\+H\\\\|\\!H\\*\\|L\\+\\!H\\*\\|L\\*\\+\\!H\\)")) 
  809.                        ;GM: excluded %H (returns nil for last target)
  810.   (let ((nas (next_accent_start syl))
  811.     (syls (item.feat syl 'syllable_start))
  812.     (syle (item.feat syl 'syllable_end))
  813.     (las (ttt_last_target_time syl)))
  814.     (if (>= printdebug  3)
  815.     (begin (print (format nil "nas: %l syls: %l syle %l las %l" nas syls syle las))))
  816.     (cond
  817.      ((and (< (- nas las) 0.5)
  818.        (> (- nas las) 0.25)
  819.        (< syls (+ (/ (- nas las) 2.0) (ttt_last_target_time syl)))
  820.        (> syle (+ (/ (- nas las) 2.0) (ttt_last_target_time syl)))) 1)
  821.      ((and (> (- nas las) 0.5)
  822.        (< syls (+ (ttt_last_target_time syl) 0.25))
  823.        (> syle (+ (ttt_last_target_time syl) 0.25))) 2)
  824.      ((and (> (- nas las) 0.5)
  825.        (< syls (- nas 0.25))
  826.        (> syle (- nas 0.25))) 3)
  827.      (t 0))))
  828.  (t 0))) 
  829.    
  830.        
  831.  
  832. (define (lh_condition syl)
  833. "(lh_condition syl)
  834. Function to determine the need for extra target points between an L and an H
  835. Returns: 1 - first extra target required
  836.          2 - second extra target required
  837.          0 - no target required.
  838. "
  839. (if (>= printdebug  4)
  840.     (begin (print "Entering LH_condition")))
  841. (cond
  842.  ((and (eq 0 (item.feat syl 'accented))
  843.        (string-matches (last_accent_type syl) "\\(L\\*\\)")
  844.        (string-matches (next_accent_type syl)
  845.                "\\(H\\*\\|H\\-\\|H\\-L\\%\\|H\\-H\\%\\)"))
  846.   (cond
  847.    ((and (eq 1 (last_accent syl))
  848.      (< 2 (next_accent syl))) 1)
  849.    ((and (< 2 (last_accent syl))
  850.      (eq 1 (next_accent syl))) 2)
  851.    (t 0)))
  852.  (t 0)))
  853.  
  854. (define (hl_condition syl)
  855. "(lh_condition syl)
  856. Function to determine the need for extra target points between an H and an L
  857. Returns: 1 - extra target required
  858.          0 - no target required.
  859. "
  860. (if (>= printdebug  4) 
  861.     (begin (print "Entering HL_condition")))
  862. (cond
  863.  ((and (eq 0 (item.feat syl 'accented))
  864.        (string-matches (next_accent_type syl)
  865.            "\\(L\\*\\|L\\+H\\*\\|L\\+\\!H\\*\\|L\\*\\+H\\|L\\*\\+!H\\|L\\-\\|L\\-L\\%\\|L-H\\%\\)")
  866.        (string-matches (last_accent_type syl)
  867.                "\\(H\\*\\|L\\+H\\*\\|L\\*\\+H\\\\|\\!H\\*\\|L\\+\\!H\\*\\|L\\*\\+\\!H\\|\\%H\\)")
  868.                        ;MDS: added !H's
  869.        (eq 1 (last_accent syl))
  870.  
  871.        ;; fall faster! -MDS
  872.        (<= 2 (next_accent syl))) 1)
  873.  (t 0)))
  874.  
  875. (define (next_accent syl)
  876. "(next_accent syl)
  877. Wrapper for c++ func ff_next_accent.
  878. Returns the number of the syllables to the next accent in the following format.
  879. 0 - no next accent
  880. 1 - next syllable
  881. 2 - next next syllable
  882. etc..."
  883. (if (>= printdebug  4) 
  884.     (begin (print "Entering next_accent")))
  885. (cond
  886.  ((eq 0 (next_accent_type syl)) 0)
  887.  (t (+ (item.feat syl 'next_accent) 1))))
  888.  
  889. ;; Fixed bug that crashed complex phrase tones. - MDS
  890. ;; Not sure how else to get a big number...
  891. (define infinity (/ 1 0))
  892.  
  893. ;; Modified to include current accent as well -MDS
  894.  
  895. (define (last_accent syl)
  896. "(last_accent syl)
  897. Wrapper for c++ func ff_last_accent.
  898. Returns the number of the syllables to the previous accent in the following format.
  899. 0 - accent on current syllable
  900. 1 - prev syllable
  901. 2 - prev to prev syllable
  902. etc...
  903. infinity - no previous syllable"
  904. (if (>= printdebug  4) 
  905.     (begin (print "Entering last_accent")))
  906. (cond
  907.  ((not (equal? "NONE" (item.feat syl 'tobi_accent))) 0)
  908.  ((equal? 0 (last_accent_type syl)) infinity)
  909.  (t (+  (item.feat syl 'last_accent) 1))))
  910.  
  911. (define (next_accent_type syl)
  912. "(next_accent_type syl)
  913. Returns the type of the next accent."
  914. (cond 
  915.  ((not (eq 0 (item.feat syl "n.R:Intonation.daughter1.name")))
  916.   (item.feat syl "n.R:Intonation.daughter1.name"))
  917.  ((eq 0 (item.feat syl 'syl_out)) 0)  ;;GM real ip_final would be better
  918.  (t (next_accent_type (item.relation.next syl 'Syllable)))))
  919.  
  920. (define (last_accent_type syl)
  921. "(last_accent_type syl)
  922. Returns the type of the last (previous)  accent."
  923. (if (>= printdebug  4) 
  924.     (begin (print "Entering last_accent_type")))
  925. (cond
  926.   ((not (equal? "NONE"  (item.feat syl 'p.tobi_endtone)))
  927.    (item.feat syl 'R:Syllable.p.tobi_endtone))
  928.   ((not (equal? "NONE"  (item.feat syl 'p.tobi_accent)))
  929.    (item.feat syl 'R:Syllable.p.tobi_accent))
  930.   ((eq 0 (item.feat syl 'syl_in)) 0)  ;;GM real ip_initial would be better
  931.   (t (last_accent_type (item.prev syl 'Syllable)))))
  932.  
  933. (define (next_accent_start syl)
  934. "(next_accent_start syl)
  935. Returns the start time  of the vowel of next accented syllable"
  936. (if (>= printdebug 4) 
  937.     (begin (print "Entering next_accent_start")))
  938. (cond 
  939.  ((not (eq 0 (item.feat syl "n.R:Intonation.daughter1.name")))
  940.   (item.feat syl "R:Syllable.n.syllable_start")) ;;GM vowel start would be better
  941.  ((eq 0 (item.feat syl 'syl_out)) 0)
  942.  (t (next_accent_start (item.relation.next syl 'Syllable)))))
  943.  
  944. ; new features (not used yet)
  945.  
  946. (define (ip_final syl)
  947.   "(ip_final SYL)
  948.   returns 1 if the syllable is the final syllable of an 
  949.   ip (intermediate phrase)"
  950.   (cond  
  951.    ((or (equal? 0 (item.feat syl "syl_out"))
  952.        (equal? "L-" (item.feat syl "tobi_endtone"))
  953.        (equal? "H-" (item.feat syl "tobi_endtone"))
  954.        (equal? "!H-" (item.feat syl "tobi_endtone"))) 1)
  955.    (t 0)))
  956.  
  957. (define (ip_initial syl)
  958.   "(ip_initial SYL)
  959.   returns 1 if the syllable is the initial syllable of an 
  960.   ip (intermediate phrase)"
  961.   (cond
  962.    ((equal? 0 (item.feat syl "syl_in"))
  963.     1)
  964.    ((equal? 1 (ip_final (item.relation.prev syl 'Syllable)))
  965.     1)
  966.    (t 0)))
  967.  
  968. ;; NEXT TWO FUNCTIONS ARE NEW - MDS
  969. (define (ip_one_syllable_case syl)
  970.   "(ip_one_syllable_case SYL)
  971.   returns true if the syllable is the initial syllable of an 
  972.   ip (intermediate phrase) and doesn't itself contain a complex
  973.   tone that starts opposite this syllable's accent"
  974.   (if (eqv? 0 (ip_initial syl))
  975.       0
  976.       (let ((accent (item.feat syl "tobi_accent"))
  977.         (tone (item.feat syl "tobi_endtone")))
  978.     (cond
  979.       ((and (equal? tone "L-H%")
  980.         (or (equal? accent "H*")
  981.             (equal? accent "!H*")
  982.             (equal? accent "L+H*")
  983.             (equal? accent "L+!H*")
  984.             (equal? accent "L*+H")
  985.             (equal? accent "L*+!H*")
  986.             (equal? accent "H+!H*")))
  987.        0)
  988.       ((and (or (equal? tone "H-L%")
  989.             (equal? tone "!H-L%"))
  990.         (equal? accent "L*"))
  991.        0)
  992.       (t
  993.        1)))))
  994.  
  995. (define (hstar_weak_target syl)
  996.   (if (and (equal? 0 (item.feat syl 'asyl_in))
  997.        (member (next_accent_type syl)
  998.            (list "L*" "L*+H" "L*+!H" "L+H*" "L+!H*")))
  999.       1
  1000.       0))
  1001.        
  1002. (provide 'tobi_rules)
  1003.